home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / gfxlib.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  48KB  |  1,683 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * graphics.library emulation
  5.   *
  6.   * Copyright 1996, 1997 Bernd Schmidt
  7.   *
  8.   * Ideas for this:
  9.   * Rewrite layers completely. When there are lots of windows on the screen
  10.   * it can take 3 minutes to update everything after resizing or moving one
  11.   * (at least with Kick 1.3). Hide the internal structure of the layers as far
  12.   * as possible, keep most of the data in emulator space so we save copying/
  13.   * conversion time. Programs really shouldn't do anything directly with the
  14.   * Layer or ClipRect structures.
  15.   * This means that a lot of graphics.library functions will have to be
  16.   * rewritten as well.
  17.   * Once that's done, add support for non-planar bitmaps. Conveniently, the
  18.   * struct Bitmap has an unused pad field which we could abuse as some sort of
  19.   * type field. Need to add chunky<->planar conversion routines to get it
  20.   * going, plus variants of all the drawing functions for speed reasons.
  21.   *
  22.   * When it becomes necessary to convert a structure from Amiga memory, make
  23.   * a function with a name ending in ..FA, which takes a pointer to the
  24.   * native structure and a uaecptr and returns the native pointer.
  25.   */
  26.  
  27. #include "sysconfig.h"
  28. #include "sysdeps.h"
  29.  
  30. #include <assert.h>
  31.  
  32. #include "config.h"
  33. #include "options.h"
  34. #include "threaddep/penguin.h"
  35. #include "memory.h"
  36. #include "custom.h"
  37. #include "readcpu.h"
  38. #include "newcpu.h"
  39. #include "xwin.h"
  40. #include "autoconf.h"
  41. #include "osemu.h"
  42. #include "osdep/exectasks.h"
  43.  
  44. #ifdef USE_EXECLIB
  45.  
  46. /* Uniq list management. Should be in a separate file. */
  47. struct uniq_head {
  48.     struct uniq_head *next;
  49.     uae_u32 uniq;
  50. };
  51.  
  52. typedef struct {
  53.     struct uniq_head *head;
  54.     uae_u32 uniq;
  55. } uniq_list;
  56.  
  57. #define UNIQ_INIT { NULL, 1 }
  58.  
  59. static void init_uniq(uniq_list *list)
  60. {
  61.     list->head = NULL;
  62.     list->uniq = 1;
  63. }
  64.  
  65. static struct uniq_head *find_uniq (uniq_list *a, uae_u32 uniq)
  66. {
  67.     struct uniq_head *b = a->head;
  68.     while (b && b->uniq != uniq)
  69.     b = b->next;
  70.     if (!b)
  71.     write_log("Couldn't find structure. Bad\n");
  72.     return b;
  73. }
  74.  
  75. static struct uniq_head *find_and_rem_uniq (uniq_list *a, uae_u32 uniq)
  76. {
  77.     struct uniq_head **b = &a->head, *c;
  78.     while (*b && (*b)->uniq != uniq)
  79.     b = &(*b)->next;
  80.     c = *b;
  81.     if (!c)
  82.     write_log("Couldn't find structure. Bad\n");
  83.     else
  84.     *b = c->next;
  85.     return c;
  86. }
  87.  
  88. static void add_uniq (uniq_list *a, struct uniq_head *item, uaecptr amem)
  89. {
  90.     item->uniq = a->uniq++;
  91.     put_long(amem, item->uniq);
  92.     if (a->uniq == 0)
  93.     a->uniq++;
  94.     item->next = a->head;
  95.     a->head = item;
  96. }
  97.  
  98. /* Graphics stuff begins here */
  99. #define CLIPRECT_SIZE 40
  100. #define LAYER_SIZE 160
  101. #define LINFO_SIZE 102
  102.  
  103. static uaecptr gfxbase, layersbase;
  104.  
  105. static void do_LockLayer(uaecptr layer)
  106. {
  107. #if 0 /* Later.. */
  108.     uaecptr sigsem = layer + 72;
  109.     m68k_areg(regs, 0) = sigsem;
  110.     CallLib(get_long(4), -564);
  111. #else
  112.     m68k_areg(regs, 1) = layer;
  113.     CallLib(layersbase, -96);
  114. #endif
  115. }
  116.  
  117. static void do_UnlockLayer(uaecptr layer)
  118. {
  119.     m68k_areg(regs, 0) = layer;
  120.     CallLib(layersbase, -102);
  121. }
  122.  
  123. static uae_u32 gfxlibname, layerslibname;
  124.  
  125. struct Rectangle {
  126.     int MinX, MinY, MaxX, MaxY;
  127. };
  128.  
  129. static int GFX_PointInRectangle(uaecptr rect, int x, int y)
  130. {
  131.     uae_s16 minx = get_word(rect);
  132.     uae_s16 miny = get_word(rect+2);
  133.     uae_s16 maxx = get_word(rect+4);
  134.     uae_s16 maxy = get_word(rect+6);
  135.  
  136.     if (x < minx || x > maxx || y < miny || y > maxy)
  137.     return 0;
  138.     return 1;
  139. }
  140.  
  141. static int GFX_RectContainsRect(struct Rectangle *r1, struct Rectangle *r2)
  142. {
  143.     return (r2->MinX >= r1->MinX && r2->MaxX <= r1->MaxX
  144.         && r2->MinY >= r1->MinY && r2->MaxY <= r1->MaxY);
  145. }
  146.  
  147. static struct Rectangle *GFX_RectFA(struct Rectangle *rp, uaecptr rect)
  148. {
  149.     rp->MinX = (uae_s16)get_word(rect);
  150.     rp->MinY = (uae_s16)get_word(rect+2);
  151.     rp->MaxX = (uae_s16)get_word(rect+4);
  152.     rp->MaxY = (uae_s16)get_word(rect+6);
  153.     return rp;
  154. }
  155.  
  156. static int GFX_Bitmap_WritePixel(uaecptr bitmap, int x, int y, uaecptr rp)
  157. {
  158.     int i, offs;
  159.     unsigned int bpr = get_word (bitmap);
  160.     unsigned int rows = get_word (bitmap + 2);
  161.     uae_u16 mask;
  162.  
  163.     uae_u8 planemask = get_byte(rp + 24);
  164.     uae_u8 fgpen = get_byte(rp + 25);
  165.     uae_u8 bgpen = get_byte(rp + 26);
  166.     uae_u8 drmd = get_byte(rp + 28);
  167.     uae_u8 pen = drmd & 4 ? bgpen : fgpen;
  168.  
  169.     if (x < 0 || y < 0 || x >= 8*bpr || y >= rows)
  170.     return -1;
  171.  
  172.     offs = y*bpr + (x & ~15)/8;
  173.  
  174.     for (i = 0; i < get_byte (bitmap + 5); i++) {
  175.     uaecptr planeptr;
  176.     uae_u16 data;
  177.  
  178.     if ((planemask & (1 << i)) == 0)
  179.         continue;
  180.  
  181.     planeptr = get_long(bitmap + 8 + i*4);
  182.     data = get_word(planeptr + offs);
  183.  
  184.     mask = 0x8000 >> (x & 15);
  185.  
  186.     if (drmd & 2) {
  187.         if ((pen & (1 << i)) != 0)
  188.         data ^=mask;
  189.     } else {
  190.         data &= ~mask;
  191.         if ((pen & (1 << i)) != 0)
  192.         data |= mask;
  193.     }
  194.     put_word(planeptr + offs, data);
  195.     }
  196.     return 0;
  197. }
  198.  
  199. int GFX_WritePixel(uaecptr rp, int x, int y)
  200. {
  201.     int v;
  202.     uaecptr layer = get_long(rp);
  203.     uaecptr bitmap = get_long(rp + 4);
  204.     uaecptr cliprect;
  205.     int x2, y2;
  206.  
  207.     if (bitmap == 0) {
  208.     fprintf(stderr, "bogus RastPort in WritePixel\n");
  209.     return -1;
  210.     }
  211.  
  212.     /* Easy case first */
  213.     if (layer == 0) {
  214.     return GFX_Bitmap_WritePixel(bitmap, x, y, rp);
  215.     }
  216.     do_LockLayer(layer);
  217.     /*
  218.      * Now, in theory we ought to obtain the semaphore.
  219.      * Since we don't, the programs will happily write into the raster
  220.      * even though we are currently moving the window around.
  221.      * Not good.
  222.      */
  223.  
  224.     x2 = x + (uae_s16)get_word(layer + 16);
  225.     y2 = y + (uae_s16)get_word(layer + 18);
  226.  
  227.     if (!GFX_PointInRectangle (layer + 16, x2, y2)) {
  228.     do_UnlockLayer(layer);
  229.     return -1;
  230.     }
  231.     /* Find the right ClipRect */
  232.     cliprect = get_long(layer + 8);
  233.     while (cliprect != 0 && !GFX_PointInRectangle (cliprect + 16, x2, y2))
  234.     cliprect = get_long(cliprect);
  235.     if (cliprect == 0) {
  236.     /* Don't complain: The "Dots" demo does this all the time. I
  237.      * suppose if we can't find a ClipRect, we aren't supposed to draw
  238.      * the dot.
  239.      */
  240.     /*fprintf(stderr, "Weirdness in WritePixel\n");*/
  241.     v = -1;
  242.     } else if (get_long(cliprect + 8) == 0) {
  243.     v = GFX_Bitmap_WritePixel(bitmap, x2, y2, rp);
  244.     } else if (get_long(cliprect + 12) == 0) {
  245.     /* I don't really know what to do here... */
  246.     v = 0;
  247.     } else {
  248.     /* This appears to be normal for smart refresh layers which are obscured */
  249.     v = GFX_Bitmap_WritePixel (get_long(cliprect + 12), x2 - (uae_s16)get_word(cliprect + 16),
  250.                    y2 - (uae_s16)get_word(cliprect + 18), rp);
  251.     }
  252.     do_UnlockLayer(layer);
  253.     return v;
  254. }
  255.  
  256.  
  257. static uae_u32 gfxl_WritePixel(void) { return GFX_WritePixel(m68k_areg(regs, 1), (uae_s16)m68k_dreg(regs, 0), (uae_s16)m68k_dreg(regs, 1)); }
  258.  
  259. static uae_u32 gfxl_BltClear(void)
  260. {
  261.     uaecptr mem=m68k_areg(regs, 1);
  262.     uae_u8 *mptr = chipmem_bank.xlateaddr(m68k_areg(regs, 1));
  263.     uae_u32 count=m68k_dreg(regs, 0);
  264.     uae_u32 flags=m68k_dreg(regs, 1);
  265.     unsigned int i;
  266.     uae_u32 pattern;
  267.  
  268.     if ((flags & 2) == 2){
  269.     /* count is given in Rows / Bytes per row */
  270.     count=(count & 0xFFFF) * (count >> 16);
  271.     }
  272.  
  273.     if ((mem & 1) != 0 || (count & 1) != 0)
  274.     fprintf(stderr, "gfx: BltClear called with odd parameters\n");
  275.  
  276.     /* Bit 2 set means use pattern (V36+ only, but we might as well emulate
  277.      * it always) */
  278.     if ((flags & 4) == 0)
  279.     pattern = 0;
  280.     else
  281.     pattern= ((flags >> 16) & 0xFFFF) | (flags & 0xFFFF0000ul);
  282.  
  283.     if ((pattern & 0xFF) == ((pattern >> 8) & 0xFF)) {
  284.     memset(mptr, pattern, count);
  285.     return 0;
  286.     }
  287.  
  288.     for(i = 0; i < count; i += 4)
  289.     chipmem_bank.lput(mem+i, pattern);
  290.  
  291.     if ((count & 3) != 0)
  292.     chipmem_bank.wput(mem + i - 4, pattern);
  293.  
  294.     return 0;
  295. }
  296.  
  297. static uae_u32 gfxl_BltBitmap(void)
  298. {
  299.     uaecptr srcbitmap = m68k_areg(regs, 0), dstbitmap = m68k_areg(regs, 1);
  300.     int srcx = (uae_s16)m68k_dreg(regs, 0), srcy = (uae_s16)m68k_dreg(regs, 1);
  301.     int dstx = (uae_s16)m68k_dreg(regs, 2), dsty = (uae_s16)m68k_dreg(regs, 3);
  302.     int sizex = (uae_s16)m68k_dreg(regs, 4), sizey = (uae_s16)m68k_dreg(regs, 5);
  303.     uae_u8 minterm = (uae_u8)m68k_dreg(regs, 6), mask = m68k_dreg(regs, 7);
  304.     return 0; /* sam: a return was missing here ! */
  305. }
  306.  
  307. static uaecptr amiga_malloc(int len)
  308. {
  309.     m68k_dreg(regs, 0) = len;
  310.     m68k_dreg(regs, 1) = 1; /* MEMF_PUBLIC */
  311.     return CallLib(get_long(4), -198); /* AllocMem */
  312. }
  313.  
  314. static void amiga_free(uaecptr addr, int len)
  315. {
  316.     m68k_areg(regs, 1) = addr;
  317.     m68k_dreg(regs, 0) = len;
  318.     CallLib(get_long(4), -210); /* FreeMem */
  319. }
  320.  
  321. /*
  322.  * Region handling code
  323.  *
  324.  * General ideas stolen from xc/verylongpath/miregion.c
  325.  *
  326.  * The Clear code is untested. And and Or seem to work, Xor is only used
  327.  * by the 1.3 Prefs program and seems to work, too.
  328.  */
  329.  
  330. struct RegionRectangle {
  331.     struct RegionRectangle *Next,*Prev;
  332.     struct Rectangle bounds;
  333. };
  334.  
  335. struct Region {
  336.     struct Rectangle bounds;
  337.     struct RegionRectangle *RegionRectangle;
  338. };
  339.  
  340. struct RectList {
  341.     int count;
  342.     int space;
  343.     struct Rectangle bounds;
  344.     struct Rectangle *rects;
  345. };
  346.  
  347. struct BandList {
  348.     int count;
  349.     int space;
  350.     int *miny, *maxy;
  351. };
  352.  
  353. static void init_bandlist(struct BandList *bl)
  354. {
  355.     bl->count = 0;
  356.     bl->space = 20;
  357.     bl->miny = (int *)malloc(20*sizeof(int));
  358.     bl->maxy = (int *)malloc(20*sizeof(int));
  359. }
  360.  
  361. static void dup_bandlist(struct BandList *to, struct BandList *from)
  362. {
  363.     to->count = from->count;
  364.     to->space = to->count+4;
  365.     to->miny = (int *)malloc (to->space*sizeof(int));
  366.     to->maxy = (int *)malloc (to->space*sizeof(int));
  367.     memcpy(to->miny, from->miny, to->count*sizeof(int));
  368.     memcpy(to->maxy, from->maxy, to->count*sizeof(int));
  369. }
  370.  
  371. static __inline__ void add_band(struct BandList *bl, int miny, int maxy, int pos)
  372. {
  373.     if (bl->count == bl->space) {
  374.     bl->space += 20;
  375.     bl->miny = (int *)realloc(bl->miny, bl->space*sizeof(int));
  376.     bl->maxy = (int *)realloc(bl->maxy, bl->space*sizeof(int));
  377.     }
  378.     memmove(bl->miny + pos + 1, bl->miny + pos, (bl->count - pos) * sizeof(int));
  379.     memmove(bl->maxy + pos + 1, bl->maxy + pos, (bl->count - pos) * sizeof(int));
  380.     bl->count++;
  381.     bl->miny[pos] = miny;
  382.     bl->maxy[pos] = maxy;
  383. }
  384.  
  385. static void init_rectlist(struct RectList *rl)
  386. {
  387.     rl->count = 0;
  388.     rl->space = 100;
  389.     rl->bounds.MinX = rl->bounds.MinY = rl->bounds.MaxX = rl->bounds.MaxY = 0;
  390.     rl->rects = (struct Rectangle *)malloc(100*sizeof(struct Rectangle));
  391. }
  392.  
  393. static void dup_rectlist(struct RectList *to, struct RectList *from)
  394. {
  395.     to->count = from->count;
  396.     to->space = to->count+4;
  397.     to->bounds = from->bounds;
  398.     to->rects = (struct Rectangle *)malloc (to->space*sizeof(struct Rectangle));
  399.     memcpy(to->rects, from->rects, to->count*sizeof(struct Rectangle));
  400. }
  401.  
  402. static __inline__ void add_rect(struct RectList *rl, struct Rectangle r)
  403. {
  404.     if (rl->count == 0)
  405.     rl->bounds = r;
  406.     else {
  407.     if (r.MinX < rl->bounds.MinX)
  408.         rl->bounds.MinX = r.MinX;
  409.     if (r.MinY < rl->bounds.MinY)
  410.         rl->bounds.MinY = r.MinY;
  411.     if (r.MaxX > rl->bounds.MaxX)
  412.         rl->bounds.MaxX = r.MaxX;
  413.     if (r.MaxY > rl->bounds.MaxY)
  414.         rl->bounds.MaxY = r.MaxY;
  415.     }
  416.     if (rl->count == rl->space) {
  417.     rl->space += 100;
  418.     rl->rects = (struct Rectangle *)realloc(rl->rects, rl->space*sizeof(struct Rectangle));
  419.     }
  420.     rl->rects[rl->count++] = r;
  421. }
  422.  
  423. static __inline__ void rem_rect(struct RectList *rl, int num)
  424. {
  425.     rl->count--;
  426.     if (num == rl->count)
  427.     return;
  428.     rl->rects[num] = rl->rects[rl->count];
  429. }
  430.  
  431. static void free_rectlist(struct RectList *rl)
  432. {
  433.     free(rl->rects);
  434. }
  435.  
  436. static void free_bandlist(struct BandList *bl)
  437. {
  438.     free(bl->miny);
  439.     free(bl->maxy);
  440. }
  441.  
  442. static int regionrect_cmpfn(const void *a, const void *b)
  443. {
  444.     struct Rectangle *ra = (struct Rectangle *)a;
  445.     struct Rectangle *rb = (struct Rectangle *)b;
  446.  
  447.     if (ra->MinY < rb->MinY)
  448.     return -1;
  449.     if (ra->MinY > rb->MinY)
  450.     return 1;
  451.     if (ra->MinX < rb->MinX)
  452.     return -1;
  453.     if (ra->MinX > rb->MinX)
  454.     return 1;
  455.     if (ra->MaxX < rb->MaxX)
  456.     return -1;
  457.     return 1;
  458. }
  459.  
  460. static __inline__ int min(int x, int y)
  461. {
  462.     return x < y ? x : y;
  463. }
  464.  
  465. static __inline__ int max(int x, int y)
  466. {
  467.     return x > y ? x : y;
  468. }
  469.  
  470. static void add_rect_to_bands(struct BandList *bl, struct Rectangle *rect)
  471. {
  472.     int j;
  473.     struct Rectangle tmpr = *rect;
  474.  
  475.     for (j = 0; j < bl->count; j++) {
  476.     /* Is the current band before the rectangle? */
  477.     if (bl->maxy[j] < tmpr.MinY)
  478.         continue;
  479.     /* Band already present? */
  480.     if (bl->miny[j] == tmpr.MinY && bl->maxy[j] == tmpr.MaxY)
  481.         break;
  482.     /* Completely new band? Add it */
  483.     if (bl->miny[j] > tmpr.MaxY) {
  484.         add_band(bl, tmpr.MinY, tmpr.MaxY, j);
  485.         break;
  486.     }
  487.     /* Now we know that the bands are overlapping.
  488.      * See whether they match in one point */
  489.     if (bl->miny[j] == tmpr.MinY) {
  490.         int t;
  491.         if (bl->maxy[j] < tmpr.MaxY) {
  492.         /* Rectangle exceeds band */
  493.         tmpr.MinY = bl->maxy[j]+1;
  494.         continue;
  495.         }
  496.         /* Rectangle splits band */
  497.         t = bl->maxy[j];
  498.         bl->maxy[j] = tmpr.MaxY;
  499.         tmpr.MinY = bl->maxy[j] + 1;
  500.         tmpr.MaxY = t;
  501.         continue;
  502.     } else if (bl->maxy[j] == tmpr.MaxY) {
  503.         int t;
  504.         if (bl->miny[j] > tmpr.MinY) {
  505.         /* Rectangle exceeds band */
  506.         t = bl->miny[j];
  507.         bl->miny[j] = tmpr.MinY;
  508.         bl->maxy[j] = t-1;
  509.         tmpr.MinY = t;
  510.         continue;
  511.         }
  512.         /* Rectangle splits band */
  513.         bl->maxy[j] = tmpr.MinY - 1;
  514.         continue;
  515.     }
  516.     /* Bands overlap and match in no points. Get a new band and align */
  517.     if (bl->miny[j] > tmpr.MinY) {
  518.         /* Rectangle begins before band, so make a new band before
  519.          * and adjust rectangle */
  520.         add_band(bl, tmpr.MinY, bl->miny[j] - 1, j);
  521.         tmpr.MinY = bl->miny[j+1];
  522.     } else {
  523.         /* Rectangle begins in band */
  524.         add_band(bl, bl->miny[j], tmpr.MinY - 1, j);
  525.         bl->miny[j+1] = tmpr.MinY;
  526.     }
  527.     continue;
  528.     }
  529.     if (j == bl->count)
  530.     add_band(bl, tmpr.MinY, tmpr.MaxY, j);
  531. }
  532.  
  533. static void region_addbands(struct RectList *rl, struct BandList *bl)
  534. {
  535.     int i,j;
  536.  
  537.     for (i = 0; i < rl->count; i++) {
  538.     add_rect_to_bands(bl, rl->rects + i);
  539.     }
  540. }
  541.  
  542. static void merge_bands(struct BandList *dest, struct BandList *src)
  543. {
  544.     int i;
  545.     for (i = 0; i < src->count; i++) {
  546.     struct Rectangle tmp;
  547.     tmp.MinY = src->miny[i];
  548.     tmp.MaxY = src->maxy[i];
  549.     add_rect_to_bands(dest, &tmp);
  550.     }
  551. }
  552.  
  553. static void region_splitrects_band(struct RectList *rl, struct BandList *bl)
  554. {
  555.     int i,j;
  556.     for (i = 0; i < rl->count; i++) {
  557.     for (j = 0; j < bl->count; j++) {
  558.         if (bl->miny[j] == rl->rects[i].MinY && bl->maxy[j] == rl->rects[i].MaxY)
  559.         break;
  560.         if (rl->rects[i].MinY > bl->maxy[j])
  561.         continue;
  562.         if (bl->miny[j] == rl->rects[i].MinY) {
  563.         struct Rectangle tmpr;
  564.         tmpr.MinX = rl->rects[i].MinX;
  565.         tmpr.MaxX = rl->rects[i].MaxX;
  566.         tmpr.MinY = bl->maxy[j] + 1;
  567.         tmpr.MaxY = rl->rects[i].MaxY;
  568.         add_rect(rl, tmpr); /* will be processed later */
  569.         rl->rects[i].MaxY = bl->maxy[j];
  570.         break;
  571.         }
  572.         fprintf(stderr, "Foo..\n");
  573.     }
  574.     }
  575.     qsort(rl->rects, rl->count, sizeof (struct Rectangle), regionrect_cmpfn);
  576. }
  577.  
  578. static void region_coalesce_rects(struct RectList *rl, int do_2nd_pass)
  579. {
  580.     int i,j;
  581.  
  582.     /* First pass: Coalesce horizontally */
  583.     for (i = j = 0; i < rl->count;) {
  584.     int offs = 1;
  585.     while (i + offs < rl->count) {
  586.         if (rl->rects[i].MinY != rl->rects[i+offs].MinY
  587.         || rl->rects[i].MaxY != rl->rects[i+offs].MaxY
  588.         || rl->rects[i].MaxX+1 < rl->rects[i+offs].MinX)
  589.         break;
  590.         rl->rects[i].MaxX = rl->rects[i+offs].MaxX;
  591.         offs++;
  592.     }
  593.     rl->rects[j++] = rl->rects[i];
  594.     i += offs;
  595.     }
  596.     rl->count = j;
  597.  
  598.     if (!do_2nd_pass)
  599.     return;
  600.  
  601.     /* Second pass: Coalesce bands */
  602.     for (i = 0; i < rl->count;) {
  603.     int match = 0;
  604.     for (j = i + 1; j < rl->count; j++)
  605.         if (rl->rects[i].MinY != rl->rects[j].MinY)
  606.         break;
  607.     if (j < rl->count && rl->rects[i].MaxY + 1 == rl->rects[j].MinY) {
  608.         int k;
  609.         match = 1;
  610.         for (k = 0; i+k < j; k++) {
  611.         if (j+k >= rl->count
  612.             || rl->rects[j+k].MinY != rl->rects[j].MinY)
  613.         {
  614.             match = 0; break;
  615.         }
  616.         if (rl->rects[i+k].MinX != rl->rects[j+k].MinX
  617.             || rl->rects[i+k].MaxX != rl->rects[j+k].MaxX)
  618.         {
  619.             match = 0;
  620.             break;
  621.         }
  622.         }
  623.         if (j+k < rl->count && rl->rects[j+k].MinY == rl->rects[j].MinY)
  624.         match = 0;
  625.         if (match) {
  626.         for (k = 0; i+k < j; k++)
  627.             rl->rects[i+k].MaxY = rl->rects[j].MaxY;
  628.         memmove(rl->rects + j, rl->rects + j + k, (rl->count - j - k)*sizeof(struct Rectangle));
  629.         rl->count -= k;
  630.         }
  631.     }
  632.     if (!match)
  633.         i = j;
  634.     }
  635. }
  636.  
  637. static int copy_rects (uaecptr region, struct RectList *rl)
  638. {
  639.     uaecptr regionrect;
  640.     int numrects = 0;
  641.     struct Rectangle b;
  642.     regionrect = get_long(region+8);
  643.     b.MinX = get_word(region);
  644.     b.MinY = get_word(region+2);
  645.     b.MaxX = get_word(region+4);
  646.     b.MaxY = get_word(region+6);
  647.  
  648.     while (regionrect != 0) {
  649.     struct Rectangle tmpr;
  650.  
  651.     tmpr.MinX = (uae_s16)get_word(regionrect+8)  + b.MinX;
  652.     tmpr.MinY = (uae_s16)get_word(regionrect+10) + b.MinY;
  653.     tmpr.MaxX = (uae_s16)get_word(regionrect+12) + b.MinX;
  654.     tmpr.MaxY = (uae_s16)get_word(regionrect+14) + b.MinY;
  655.     add_rect(rl, tmpr);
  656.     regionrect = get_long(regionrect);
  657.     numrects++;
  658.     }
  659.     return numrects;
  660. }
  661.  
  662. static int rect_in_region(struct RectList *rl, struct Rectangle *r)
  663. {
  664.     int i;
  665.     int miny = r->MinY;
  666.  
  667.     for (i = 0; i < rl->count; i++) {
  668.     int j;
  669.     if (rl->rects[i].MaxY < miny)
  670.         continue;
  671.     if (rl->rects[i].MinY > miny)
  672.         break;
  673.     if (rl->rects[i].MaxX < r->MinX)
  674.         continue;
  675.     if (rl->rects[i].MinX > r->MaxX)
  676.         break;
  677.     /* Overlap! */
  678.     j = i;
  679.     for (;;) {
  680.         if (rl->rects[j].MaxX > r->MaxX) {
  681.         miny = rl->rects[i].MaxY + 1;
  682.         break;
  683.         }
  684.         j++;
  685.         if (j == rl->count)
  686.         break;
  687.         if (rl->rects[j].MinX != rl->rects[j-1].MaxX+1)
  688.         break;
  689.         if (rl->rects[i].MinY != rl->rects[j].MinY)
  690.         break;
  691.     }
  692.     if (miny <= rl->rects[i].MaxY)
  693.         break;
  694.     }
  695.     return 0;
  696. }
  697.  
  698. typedef void (*regionop)(struct RectList *,struct RectList *,struct RectList *);
  699.  
  700. static void region_do_ClearRegionRegion(struct RectList *rl1,struct RectList *rl2,
  701.                     struct RectList *rl3)
  702. {
  703.     int i,j;
  704.  
  705.     for (i = j = 0; i < rl2->count && j < rl1->count;) {
  706.     struct Rectangle tmpr;
  707.  
  708.     while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  709.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  710.             && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  711.            && j < rl1->count)
  712.         j++;
  713.     if (j >= rl1->count)
  714.         break;
  715.     while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  716.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  717.             && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  718.            && i < rl2->count)
  719.     {
  720.         add_rect(rl3, rl2->rects[i]);
  721.         i++;
  722.     }
  723.     if (i >= rl2->count)
  724.         break;
  725.  
  726.     tmpr = rl2->rects[i];
  727.  
  728.     while (i < rl2->count && j < rl1->count
  729.            && rl1->rects[j].MinY == tmpr.MinY
  730.            && rl2->rects[i].MinY == tmpr.MinY
  731.            && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  732.            && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  733.     {
  734.         int oldmin = tmpr.MinX;
  735.         int oldmax = tmpr.MaxX;
  736.         if (tmpr.MinX < rl1->rects[j].MinX) {
  737.         tmpr.MaxX = rl1->rects[j].MinX - 1;
  738.         add_rect(rl3, tmpr);
  739.         }
  740.         if (oldmax <= rl1->rects[j].MaxX) {
  741.         i++;
  742.         if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY)
  743.             tmpr = rl2->rects[i];
  744.         } else {
  745.         tmpr.MinX = rl1->rects[j].MaxX + 1;
  746.         tmpr.MaxX = oldmax;
  747.         j++;
  748.         }
  749.     }
  750.     }
  751.     for(; i < rl2->count; i++)
  752.     add_rect(rl3, rl2->rects[i]);
  753. }
  754.  
  755. static void region_do_AndRegionRegion(struct RectList *rl1,struct RectList *rl2,
  756.                       struct RectList *rl3)
  757. {
  758.     int i,j;
  759.  
  760.     for (i = j = 0; i < rl2->count && j < rl1->count;) {
  761.     while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  762.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  763.             && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  764.            && j < rl1->count)
  765.         j++;
  766.     if (j >= rl1->count)
  767.         break;
  768.     while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  769.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  770.             && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  771.            && i < rl2->count)
  772.         i++;
  773.     if (i >= rl2->count)
  774.         break;
  775.     if (rl1->rects[j].MinY == rl2->rects[i].MinY
  776.         && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  777.         && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  778.     {
  779.         /* We have an intersection! */
  780.         struct Rectangle tmpr;
  781.         tmpr = rl2->rects[i];
  782.         if (tmpr.MinX < rl1->rects[j].MinX)
  783.         tmpr.MinX = rl1->rects[j].MinX;
  784.         if (tmpr.MaxX > rl1->rects[j].MaxX)
  785.         tmpr.MaxX = rl1->rects[j].MaxX;
  786.         add_rect(rl3, tmpr);
  787.         if (rl1->rects[j].MaxX == rl2->rects[i].MaxX)
  788.         i++, j++;
  789.         else if (rl1->rects[j].MaxX > rl2->rects[i].MaxX)
  790.         i++;
  791.         else
  792.         j++;
  793.     }
  794.     }
  795. }
  796.  
  797. static void region_do_OrRegionRegion(struct RectList *rl1,struct RectList *rl2,
  798.                      struct RectList *rl3)
  799. {
  800.     int i,j;
  801.  
  802.     for (i = j = 0; i < rl2->count && j < rl1->count;) {
  803.     while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  804.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  805.             && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  806.            && j < rl1->count)
  807.     {
  808.         add_rect(rl3, rl1->rects[j]);
  809.         j++;
  810.     }
  811.     if (j >= rl1->count)
  812.         break;
  813.     while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  814.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  815.             && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  816.            && i < rl2->count)
  817.     {
  818.         add_rect(rl3, rl2->rects[i]);
  819.         i++;
  820.     }
  821.     if (i >= rl2->count)
  822.         break;
  823.     if (rl1->rects[j].MinY == rl2->rects[i].MinY
  824.         && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  825.         && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  826.     {
  827.         /* We have an intersection! */
  828.         struct Rectangle tmpr;
  829.         tmpr = rl2->rects[i];
  830.         if (tmpr.MinX > rl1->rects[j].MinX)
  831.         tmpr.MinX = rl1->rects[j].MinX;
  832.         if (tmpr.MaxX < rl1->rects[j].MaxX)
  833.         tmpr.MaxX = rl1->rects[j].MaxX;
  834.         i++; j++;
  835.         for (;;) {
  836.         int cont = 0;
  837.         if (j < rl1->count && rl1->rects[j].MinY == tmpr.MinY
  838.             && tmpr.MaxX+1 >= rl1->rects[j].MinX) {
  839.             if (tmpr.MaxX < rl1->rects[j].MaxX)
  840.             tmpr.MaxX = rl1->rects[j].MaxX;
  841.             j++; cont = 1;
  842.         }
  843.         if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY
  844.             && tmpr.MaxX+1 >= rl2->rects[i].MinX) {
  845.             if (tmpr.MaxX < rl2->rects[i].MaxX)
  846.             tmpr.MaxX = rl2->rects[i].MaxX;
  847.             i++; cont = 1;
  848.         }
  849.         if (!cont)
  850.             break;
  851.         }
  852.         add_rect(rl3, tmpr);
  853.     }
  854.     }
  855.     for(; i < rl2->count; i++)
  856.     add_rect(rl3, rl2->rects[i]);
  857.     for(; j < rl1->count; j++)
  858.     add_rect(rl3, rl1->rects[j]);
  859. }
  860.  
  861. static void region_do_XorRegionRegion(struct RectList *rl1,struct RectList *rl2,
  862.                       struct RectList *rl3)
  863. {
  864.     int i,j;
  865.  
  866.     for (i = j = 0; i < rl2->count && j < rl1->count;) {
  867.     struct Rectangle tmpr1, tmpr2;
  868.  
  869.     while ((rl1->rects[j].MinY < rl2->rects[i].MinY
  870.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  871.             && rl1->rects[j].MaxX < rl2->rects[i].MinX))
  872.            && j < rl1->count)
  873.     {
  874.         add_rect(rl3, rl1->rects[j]);
  875.         j++;
  876.     }
  877.     if (j >= rl1->count)
  878.         break;
  879.     while ((rl1->rects[j].MinY > rl2->rects[i].MinY
  880.         || (rl1->rects[j].MinY == rl2->rects[i].MinY
  881.             && rl1->rects[j].MinX > rl2->rects[i].MaxX))
  882.            && i < rl2->count)
  883.     {
  884.         add_rect(rl3, rl2->rects[i]);
  885.         i++;
  886.     }
  887.     if (i >= rl2->count)
  888.         break;
  889.  
  890.     tmpr2 = rl2->rects[i];
  891.     tmpr1 = rl1->rects[j];
  892.  
  893.     while (i < rl2->count && j < rl1->count
  894.            && rl1->rects[j].MinY == tmpr1.MinY
  895.            && rl2->rects[i].MinY == tmpr1.MinY
  896.            && rl1->rects[j].MinX <= rl2->rects[i].MaxX
  897.            && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
  898.     {
  899.         int oldmin2 = tmpr2.MinX;
  900.         int oldmax2 = tmpr2.MaxX;
  901.         int oldmin1 = tmpr1.MinX;
  902.         int oldmax1 = tmpr1.MaxX;
  903.         int need_1 = 0, need_2 = 0;
  904.  
  905.         if (tmpr2.MinX > tmpr1.MinX    && tmpr2.MaxX < tmpr1.MaxX)
  906.         {
  907.         /*
  908.          *    ###########
  909.          *       ****
  910.          */
  911.         tmpr1.MaxX = tmpr2.MinX - 1;
  912.         add_rect(rl3, tmpr1);
  913.         tmpr1.MaxX = oldmax1;
  914.         tmpr1.MinX = tmpr2.MaxX + 1;
  915.         add_rect(rl3, tmpr1);
  916.         need_2 = 1;
  917.         } else if (tmpr2.MinX > tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  918.         /*
  919.          *    ##########
  920.          *       *********
  921.          */
  922.         tmpr1.MaxX = tmpr2.MinX - 1;
  923.         add_rect(rl3, tmpr1);
  924.         tmpr2.MinX = oldmax1 + 1;
  925.         add_rect(rl3, tmpr2);
  926.         need_1 = 1;
  927.         } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX < tmpr1.MaxX) {
  928.         /*
  929.          *       ##########
  930.          *    *********
  931.          */
  932.         tmpr2.MaxX = tmpr1.MinX - 1;
  933.         add_rect(rl3, tmpr2);
  934.         tmpr1.MinX = oldmax2 + 1;
  935.         add_rect(rl3, tmpr1);
  936.         need_2 = 1;
  937.         } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  938.         /*
  939.          *       ###
  940.          *    *********
  941.          */
  942.         tmpr2.MaxX = tmpr1.MinX - 1;
  943.         add_rect(rl3, tmpr2);
  944.         tmpr2.MaxX = oldmax2;
  945.         tmpr2.MinX = tmpr1.MaxX + 1;
  946.         add_rect(rl3, tmpr2);
  947.         need_1 = 1;
  948.         } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX < tmpr1.MaxX) {
  949.         /*
  950.          *    #############
  951.          *    *********
  952.          */
  953.         tmpr1.MinX = tmpr2.MaxX + 1;
  954.         need_2 = 1;
  955.         } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX > tmpr1.MaxX) {
  956.         /*
  957.          *    #########
  958.          *    *************
  959.          */
  960.         tmpr2.MinX = tmpr1.MaxX + 1;
  961.         need_1 = 1;
  962.         } else if (tmpr1.MinX < tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) {
  963.         /*
  964.          *    #############
  965.          *        *********
  966.          */
  967.         tmpr1.MaxX = tmpr2.MinX - 1;
  968.         add_rect(rl3, tmpr1);
  969.         need_2 = need_1 = 1;
  970.         } else if (tmpr1.MinX > tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) {
  971.         /*
  972.          *        #########
  973.          *    *************
  974.          */
  975.         tmpr2.MaxX = tmpr1.MinX - 1;
  976.         add_rect(rl3, tmpr2);
  977.         need_2 = need_1 = 1;
  978.         } else {
  979.         assert(tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX);
  980.         need_1 = need_2 = 1;
  981.         }
  982.         if (need_1) {
  983.         j++;
  984.         if (j < rl1->count && rl1->rects[j].MinY == tmpr1.MinY)
  985.             tmpr1 = rl1->rects[j];
  986.         }
  987.         if (need_2) {
  988.         i++;
  989.         if (i < rl2->count && rl2->rects[i].MinY == tmpr2.MinY)
  990.             tmpr2 = rl2->rects[i];
  991.         }
  992.     }
  993.     }
  994.     for(; i < rl2->count; i++)
  995.     add_rect(rl3, rl2->rects[i]);
  996.     for(; j < rl1->count; j++)
  997.     add_rect(rl3, rl1->rects[j]);
  998. }
  999.  
  1000. static uae_u32 gfxl_perform_regionop(regionop op, int with_rect)
  1001. {
  1002.     int i,j,k;
  1003.     uaecptr reg1;
  1004.     uaecptr reg2;
  1005.     uaecptr tmp, rpp;
  1006.     struct RectList rl1, rl2, rl3;
  1007.     struct BandList bl;
  1008.  
  1009.     int retval = 0;
  1010.     int numrects2;
  1011.  
  1012.     init_rectlist(&rl1); init_rectlist(&rl2); init_rectlist(&rl3);
  1013.  
  1014.     if (with_rect) {
  1015.     struct Rectangle tmpr;
  1016.     reg2 = m68k_areg(regs, 0);
  1017.     numrects2 = copy_rects(reg2, &rl2);
  1018.     tmpr.MinX = get_word(m68k_areg(regs, 1));
  1019.     tmpr.MinY = get_word(m68k_areg(regs, 1) + 2);
  1020.     tmpr.MaxX = get_word(m68k_areg(regs, 1) + 4);
  1021.     tmpr.MaxY = get_word(m68k_areg(regs, 1) + 6);
  1022.     add_rect(&rl1, tmpr);
  1023.     } else {
  1024.     reg1 = m68k_areg(regs, 0);
  1025.     reg2 = m68k_areg(regs, 1);
  1026.  
  1027.     copy_rects(reg1, &rl1);
  1028.     numrects2 = copy_rects(reg2, &rl2);
  1029.     }
  1030.  
  1031.     init_bandlist(&bl);
  1032.     region_addbands(&rl1, &bl);
  1033.     region_addbands(&rl2, &bl);
  1034.     region_splitrects_band(&rl1, &bl);
  1035.     region_splitrects_band(&rl2, &bl);
  1036.     region_coalesce_rects(&rl1, 0);
  1037.     region_coalesce_rects(&rl2, 0);
  1038.  
  1039.     (*op)(&rl1, &rl2, &rl3);
  1040.     region_coalesce_rects(&rl3, 1);
  1041.  
  1042.     rpp = reg2 + 8;
  1043.     if (rl3.count < numrects2) {
  1044.     while (numrects2-- != rl3.count) {
  1045.         tmp = get_long(rpp);
  1046.         put_long(rpp, get_long(tmp));
  1047.         amiga_free(tmp, 16);
  1048.     }
  1049.     if (rl3.count > 0)
  1050.         put_long(get_long(rpp) + 4, rpp);
  1051.     } else if (rl3.count > numrects2) {
  1052.     while(numrects2++ != rl3.count) {
  1053.         uaecptr prev = get_long(rpp);
  1054.         tmp = amiga_malloc(16);
  1055.         if (tmp == 0)
  1056.         goto done;
  1057.         put_long(tmp, prev);
  1058.         put_long(tmp + 4, rpp);
  1059.         if (prev != 0)
  1060.         put_long(prev + 4, tmp);
  1061.         put_long(rpp, tmp);
  1062.     }
  1063.     }
  1064.  
  1065.     if (rl3.count > 0) {
  1066.     rpp = reg2 + 8;
  1067.     for (i = 0; i < rl3.count; i++) {
  1068.         uaecptr rr = get_long(rpp);
  1069.         put_word(rr+8, rl3.rects[i].MinX - rl3.bounds.MinX);
  1070.         put_word(rr+10, rl3.rects[i].MinY - rl3.bounds.MinY);
  1071.         put_word(rr+12, rl3.rects[i].MaxX - rl3.bounds.MinX);
  1072.         put_word(rr+14, rl3.rects[i].MaxY - rl3.bounds.MinY);
  1073.         rpp = rr;
  1074.     }
  1075.     if (get_long(rpp) != 0)
  1076.         fprintf(stderr, "BUG\n");
  1077.     }
  1078.     put_word(reg2+0, rl3.bounds.MinX);
  1079.     put_word(reg2+2, rl3.bounds.MinY);
  1080.     put_word(reg2+4, rl3.bounds.MaxX);
  1081.     put_word(reg2+6, rl3.bounds.MaxY);
  1082.     retval = 1;
  1083.  
  1084.     done:
  1085.     free_rectlist(&rl1); free_rectlist(&rl2); free_rectlist(&rl3);
  1086.     free_bandlist(&bl);
  1087.  
  1088.     return retval;
  1089. }
  1090.  
  1091. static uae_u32 gfxl_AndRegionRegion(void)
  1092. {
  1093.     return gfxl_perform_regionop(region_do_AndRegionRegion, 0);
  1094. }
  1095. static uae_u32 gfxl_XorRegionRegion(void)
  1096. {
  1097.     return gfxl_perform_regionop(region_do_XorRegionRegion, 0);
  1098. }
  1099. static uae_u32 gfxl_OrRegionRegion(void)
  1100. {
  1101.     return gfxl_perform_regionop(region_do_OrRegionRegion, 0);
  1102. }
  1103.  
  1104. static uae_u32 gfxl_ClearRectRegion(void)
  1105. {
  1106.     return gfxl_perform_regionop(region_do_ClearRegionRegion, 1);
  1107. }
  1108. static uae_u32 gfxl_OrRectRegion(void)
  1109. {
  1110.     return gfxl_perform_regionop(region_do_OrRegionRegion, 1);
  1111. }
  1112.  
  1113. static uae_u32 gfxl_AndRectRegion(void)
  1114. {
  1115.     return gfxl_perform_regionop(region_do_AndRegionRegion, 1);
  1116. }
  1117.  
  1118. static uae_u32 gfxl_XorRectRegion(void)
  1119. {
  1120.     return gfxl_perform_regionop(region_do_XorRegionRegion, 1);
  1121. }
  1122.  
  1123.  
  1124. /* Layers code */
  1125.  
  1126. static uae_u32 LY_TryLockLayer(uaecptr layer)
  1127. {
  1128.     uaecptr sigsem = layer + 72;
  1129.  
  1130.     m68k_areg(regs, 0) = sigsem;
  1131.     return CallLib(get_long(4), -576);
  1132. }
  1133.  
  1134. static void LY_LockLayer(uaecptr layer)
  1135. {
  1136.     uaecptr sigsem = layer + 72;
  1137.  
  1138.     m68k_areg(regs, 0) = sigsem;
  1139.     CallLib(get_long(4), -564);
  1140. }
  1141.  
  1142. static void LY_UnlockLayer(uaecptr layer)
  1143. {
  1144.     uaecptr sigsem = layer + 72;
  1145.  
  1146.     m68k_areg(regs, 0) = sigsem;
  1147.     CallLib(get_long(4), -570);
  1148. }
  1149.  
  1150. static void LY_LockLayerInfo(uaecptr li)
  1151. {
  1152.     uaecptr sigsem = li + 24;
  1153.  
  1154.     m68k_areg(regs, 0) = sigsem;
  1155.     CallLib(get_long(4), -564);
  1156.     put_byte(li+91, get_byte(li+91)+1);
  1157. }
  1158.  
  1159. static void LY_UnlockLayerInfo(uaecptr li)
  1160. {
  1161.     uaecptr sigsem = li + 24;
  1162.  
  1163.     put_byte(li+91, get_byte(li+91)-1);
  1164.     m68k_areg(regs, 0) = sigsem;
  1165.     CallLib(get_long(4), -570);
  1166. }
  1167.  
  1168. static void LY_LockLayers(uaecptr li)
  1169. {
  1170.     uaecptr l = get_long (li);
  1171.     LY_LockLayerInfo(li);
  1172.     while (l != 0) {
  1173.     LY_LockLayer(l);
  1174.     l = get_long(l);
  1175.     }
  1176.     LY_UnlockLayerInfo(li);
  1177. }
  1178.  
  1179. static void LY_UnlockLayers(uaecptr li)
  1180. {
  1181.     uaecptr l = get_long (li);
  1182.     LY_LockLayerInfo(li);
  1183.     while (l != 0) {
  1184.     LY_UnlockLayer(l);
  1185.     l = get_long(l);
  1186.     }
  1187.     LY_UnlockLayerInfo(li);
  1188. }
  1189.  
  1190. #define LAYER_CLUELESS   0x8000 /* Indicates we know nothing about the layer's regions. */
  1191. #define LAYER_CR_CHANGED 0x4000 /* Indicates that the cliprects in Amiga memory need to be re-done */
  1192. #define LAYER_REDO       0x2000 /* Indicates that we have regions, but they are bogus. */
  1193.  
  1194. static uae_u32 layer_uniq = 1;
  1195.  
  1196. struct MyLayerInfo {
  1197.     struct uniq_head head;
  1198.     uaecptr amigaos_linfo;
  1199.     uniq_list layer_list;
  1200. };
  1201.  
  1202. struct MyLayer {
  1203.     struct uniq_head head;
  1204.     uaecptr amigaos_layer, rastport;
  1205.     struct Rectangle bounds;
  1206.     struct RectList clipregion;
  1207.     struct RectList obscured;
  1208.     struct RectList visible;
  1209.     struct BandList big_bands; /* created by obscuring layers */
  1210.     struct BandList small_bands; /* big_bands + those from clipregion */
  1211.     struct RectList damage;
  1212.     struct BandList damage_bands;
  1213.     struct MyLayerInfo *mli;
  1214. };
  1215.  
  1216. static uniq_list MyLayerInfo_list = UNIQ_INIT;
  1217.  
  1218. static void LY_InitLayers(uaecptr li)
  1219. {
  1220.     memset (get_real_address(li), 0, 92);
  1221.     put_long(li + 0, 0); /* top layer */
  1222.     put_long(li+84, 0); /* uniq: */
  1223.     m68k_areg(regs, 0) = li + 24; CallLib(get_long(4), -558); /* InitSemaphore() */
  1224.     put_word(li+88, 0); /* flags (???) */
  1225.     put_byte(li+89, 0); /* fatten_count */
  1226.     /* @@@ How big can I assume the structure? What's all this 1.0/1.1 cruft? */
  1227. }
  1228.  
  1229. static void LY_FattenLayerInfo(uaecptr li)
  1230. {
  1231.     struct MyLayerInfo *mli;
  1232.     int fatten_count = get_byte (li + 89);
  1233.     if (fatten_count == 0) {
  1234.     mli = (struct MyLayerInfo *)malloc(sizeof(struct MyLayerInfo));
  1235.     add_uniq(&MyLayerInfo_list, &mli->head, li + 84);
  1236.     init_uniq(&mli->layer_list);
  1237.     mli->amigaos_linfo = li;
  1238.     }
  1239.     put_byte (li + 89, fatten_count + 1);
  1240. }
  1241.  
  1242. static void LY_ThinLayerInfo(uaecptr li)
  1243. {
  1244.     int fatten_count = get_byte (li + 89)-1;
  1245.     put_byte (li + 89, fatten_count);
  1246.     if (fatten_count == 0) {
  1247.     struct MyLayerInfo *mli = (struct MyLayerInfo *)find_and_rem_uniq(&MyLayerInfo_list, get_long(li+84));
  1248.     if (mli)
  1249.         free(mli);
  1250.     }
  1251. }
  1252.  
  1253. static void build_cliprect (struct MyLayer *l, struct Rectangle *bounds,
  1254.                 int obscured, uaecptr *crp, uaecptr *prev)
  1255. {
  1256.     uaecptr cr = get_long (*crp);
  1257.     if (cr == 0) {
  1258.     put_long (*crp, cr = amiga_malloc(CLIPRECT_SIZE));
  1259.     put_long (cr, 0);
  1260.     }
  1261.     *prev = cr;
  1262.     *crp = cr;
  1263.     put_word (cr + 16, bounds->MinX);
  1264.     put_word (cr + 18, bounds->MinY);
  1265.     put_word (cr + 20, bounds->MaxX);
  1266.     put_word (cr + 22, bounds->MaxY);
  1267.     put_long (cr + 8, obscured ? l->amigaos_layer : 0); /* cheat */
  1268.     put_long (cr + 12, 0); /* no smart refresh yet */
  1269. }
  1270.  
  1271. static void build_cliprects (struct MyLayer *l)
  1272. {
  1273.     uaecptr layer = l->amigaos_layer;
  1274.     uaecptr cr = layer + 8;
  1275.     uaecptr prev = 0;
  1276.     uae_u16 flags = get_word(layer + 30);
  1277.     int i;
  1278.  
  1279.     if ((flags & LAYER_CR_CHANGED) == 0)
  1280.     return;
  1281.     put_word (layer + 30, flags & ~LAYER_CR_CHANGED);
  1282.     for (i = 0; i < l->obscured.count; i++) {
  1283.     build_cliprect (l, l->obscured.rects + i, 1, &cr, &prev);
  1284.     }
  1285.     for (i = 0; i < l->visible.count; i++) {
  1286.     build_cliprect (l, l->visible.rects + i, 1, &cr, &prev);
  1287.     }
  1288.     while ((prev = get_long (cr))) {
  1289.     put_long (cr, get_long (prev));
  1290.     amiga_free (prev, CLIPRECT_SIZE);
  1291.     }
  1292. }
  1293.  
  1294. static void propagate_clueless_redo (struct MyLayerInfo *mli)
  1295. {
  1296.     /* For all CLUELESS layers, set the REDO bit for all layers below it that overlap it
  1297.      * and delete the data associated with them. */
  1298.     uaecptr current_l = get_long(mli->amigaos_linfo);
  1299.     while (current_l) {
  1300.     struct MyLayer *l = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(current_l + 24));
  1301.     if ((get_word(l->amigaos_layer + 32) & LAYER_CLUELESS) != 0) {
  1302.         uaecptr next_l = get_long(current_l);
  1303.         put_word(l->amigaos_layer + 32, get_word(l->amigaos_layer + 32) | LAYER_REDO);
  1304.         while (next_l) {
  1305.         struct MyLayer *l2 = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(next_l + 24));
  1306.         uae_u16 flags = get_word(l2->amigaos_layer + 32);
  1307.         if (l2->bounds.MinX <= l->bounds.MaxX && l->bounds.MinX <= l2->bounds.MaxX
  1308.             && l2->bounds.MinY <= l->bounds.MaxY && l->bounds.MinY <= l2->bounds.MaxY)
  1309.             put_word(l2->amigaos_layer + 32, flags | LAYER_REDO);
  1310.         if ((flags & (LAYER_REDO|LAYER_CLUELESS)) == 0) {
  1311.             free_rectlist(&l->obscured);
  1312.             free_rectlist(&l->visible);
  1313.             free_bandlist(&l->big_bands);
  1314.             free_bandlist(&l->small_bands);
  1315.         }
  1316.         next_l = get_long(next_l);
  1317.         }
  1318.     }
  1319.     current_l = get_long(current_l);
  1320.     }
  1321. }
  1322.  
  1323. static void redo_layers(struct MyLayerInfo *mli, uaecptr bm)
  1324. {
  1325.     uaecptr current_l;
  1326.     struct RectList tmp_rl;
  1327.  
  1328.     propagate_clueless_redo(mli);
  1329.     current_l = get_long(mli->amigaos_linfo);
  1330.  
  1331.     while (current_l) {
  1332.     struct MyLayer *l = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(current_l + 24));
  1333.     uae_u16 flags = get_word(l->amigaos_layer + 32);
  1334.     if ((flags & LAYER_REDO) != 0) {
  1335.         uaecptr next_l = get_long(current_l+4);
  1336.         int have_rects = 0;
  1337.  
  1338.         init_rectlist(&l->obscured);
  1339.         init_bandlist(&l->big_bands);
  1340.         add_rect_to_bands(&l->big_bands, &l->bounds);
  1341.  
  1342.         while (next_l) {
  1343.         struct MyLayer *l2 = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(next_l + 24));
  1344.         if (l2->visible.bounds.MinX <= l->bounds.MaxX && l->bounds.MinX <= l2->visible.bounds.MaxX
  1345.             && l2->visible.bounds.MinY <= l->bounds.MaxY && l->bounds.MinY <= l2->visible.bounds.MaxY
  1346.             && !rect_in_region (&l->obscured, &l2->visible.bounds))
  1347.         {
  1348.             add_rect_to_bands(&l->big_bands, &l2->visible.bounds);
  1349.             add_rect(&l->obscured, l2->visible.bounds);
  1350.             have_rects++;
  1351.         }
  1352.         next_l = get_long(next_l+4);
  1353.         }
  1354.         init_rectlist(&l->visible);
  1355.         init_rectlist(&tmp_rl);
  1356.         add_rect (&tmp_rl, l->bounds);
  1357.  
  1358.         region_splitrects_band(&l->obscured, &l->big_bands);
  1359.         region_splitrects_band(&tmp_rl, &l->big_bands);
  1360.         region_do_ClearRegionRegion(&l->obscured, &tmp_rl, &l->visible);
  1361.         flags |= LAYER_CR_CHANGED;
  1362.     }
  1363.     put_word (l->amigaos_layer + 32, flags & ~(LAYER_CLUELESS|LAYER_REDO));
  1364.     current_l = get_long(current_l);
  1365.     }
  1366. }
  1367.  
  1368. static struct MyLayer *LY_NewLayer(struct MyLayerInfo *mli, int x0, int x1, int y0, int y1,
  1369.                    uae_u16 flags, uaecptr bm, uaecptr sbm)
  1370. {
  1371.     struct MyLayer *l = (struct MyLayer *)malloc(sizeof (struct MyLayer));
  1372.     uaecptr layer = amiga_malloc(LAYER_SIZE);
  1373.     memset (get_real_address(layer), 0, LAYER_SIZE);
  1374.     l->amigaos_layer = layer;
  1375.  
  1376.     put_word(layer + 16, x0); /* bounds */
  1377.     put_word(layer + 18, y0);
  1378.     put_word(layer + 20, x1);
  1379.     put_word(layer + 22, y1);
  1380.     put_word(layer + 30, flags | LAYER_CLUELESS);
  1381.     put_long(layer + 32, flags & 4 ? sbm : 0); /* ClipRect */
  1382.     put_long(layer + 68, mli->amigaos_linfo);
  1383.     m68k_areg(regs, 0) = layer + 72; CallLib(get_long(4), -558); /* InitSemaphore() */
  1384.     add_uniq(&mli->layer_list, &l->head, layer + 24);
  1385.     l->mli = mli;
  1386.  
  1387.     l->bounds.MinX = x0;
  1388.     l->bounds.MaxX = x1;
  1389.     l->bounds.MinY = y0;
  1390.     l->bounds.MaxY = y1;
  1391.     return l;
  1392. }
  1393.  
  1394. static void LY_DeleteLayer(uaecptr layer)
  1395. {
  1396.     uaecptr cr;
  1397.     struct MyLayer *l = (struct MyLayer *)find_and_rem_uniq(&l->mli->layer_list, get_long (layer + 24));
  1398.     /* Free ClipRects */
  1399.     while ((cr = get_long (l->amigaos_layer + 8))) {
  1400.     put_long (l->amigaos_layer + 8, get_long(cr));
  1401.     amiga_free(cr, CLIPRECT_SIZE);
  1402.     }
  1403.     amiga_free (l->amigaos_layer, LAYER_SIZE);
  1404.     free(l);
  1405. }
  1406.  
  1407. static uaecptr find_behindlayer_position(uaecptr li, uae_u16 flags)
  1408. {
  1409.     uaecptr where = li;
  1410.     for (;;) {
  1411.     uaecptr other = get_long (where);
  1412.     /* End of list? */
  1413.     if (other == 0)
  1414.         break;
  1415.     /* Backdrop? */
  1416.     if ((get_word(other + 30) & 0x40) > (flags & 0x40))
  1417.         break;
  1418.     where = other;
  1419.     }
  1420.     return where;
  1421. }
  1422.  
  1423. static uaecptr LY_CreateLayer(uaecptr li, int x0, int x1, int y0, int y1,
  1424.                   uae_u16 flags, uaecptr bm, uaecptr sbm, uaecptr where)
  1425. {
  1426.     struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq(&MyLayerInfo_list, get_long (li + 84));
  1427.     struct MyLayer *l;
  1428.  
  1429.     LY_LockLayerInfo(li);
  1430.  
  1431.     l = LY_NewLayer(mli, x0, x1, y0, y1, flags, bm, sbm);
  1432.     /* Chain into list */
  1433.     put_long(l->amigaos_layer, get_long (where));
  1434.     put_long(l->amigaos_layer + 4, where == li ? 0 : where);
  1435.     if (get_long (where) != 0)
  1436.     put_long(get_long (where) + 4, l->amigaos_layer);
  1437.     put_long(where, l->amigaos_layer);
  1438.     redo_layers(mli, bm);
  1439.     build_cliprects(l);
  1440.     LY_UnlockLayerInfo(li);
  1441.     return l->amigaos_layer;
  1442. }
  1443.  
  1444. static void LY_DisposeLayerInfo(uaecptr li)
  1445. {
  1446.     LY_ThinLayerInfo(li);
  1447.     amiga_free(li, LINFO_SIZE);
  1448. }
  1449.  
  1450. static uae_u32 layers_NewLayerInfo(void)
  1451. {
  1452.     uaecptr li = amiga_malloc(LINFO_SIZE);
  1453.     LY_InitLayers(li);
  1454.     LY_FattenLayerInfo(li);
  1455.     return li;
  1456. }
  1457. static uae_u32 layers_InitLayers(void) { LY_InitLayers (m68k_areg (regs, 0)); return 0; }
  1458. static uae_u32 layers_DisposeLayerInfo(void) { LY_DisposeLayerInfo (m68k_areg (regs, 0)); return 0; }
  1459.  
  1460. static uae_u32 layers_FattenLayerInfo(void) { LY_FattenLayerInfo(m68k_areg(regs, 0)); return 0; }
  1461. static uae_u32 layers_ThinLayerInfo(void) { LY_ThinLayerInfo(m68k_areg(regs, 0)); return 0; }
  1462.  
  1463. static uae_u32 layers_CreateUpfrontLayer(void)
  1464. {
  1465.     return LY_CreateLayer(m68k_areg(regs, 0), (uae_s32)m68k_dreg(regs, 0),
  1466.               (uae_s32)m68k_dreg(regs, 1), (uae_s32)m68k_dreg(regs, 2),
  1467.               (uae_s32)m68k_dreg(regs, 3),
  1468.               m68k_dreg(regs, 4),
  1469.               m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_areg(regs, 0));
  1470. }
  1471. static uae_u32 layers_CreateBehindLayer(void)
  1472. {
  1473.     return LY_CreateLayer(m68k_areg(regs, 0), (uae_s32)m68k_dreg(regs, 0),
  1474.               (uae_s32)m68k_dreg(regs, 1), (uae_s32)m68k_dreg(regs, 2),
  1475.               (uae_s32)m68k_dreg(regs, 3),
  1476.               m68k_dreg(regs, 4),
  1477.               m68k_areg(regs, 1), m68k_areg(regs, 2),
  1478.               find_behindlayer_position (m68k_areg(regs, 0), m68k_dreg(regs, 4)));
  1479. }
  1480. static uae_u32 layers_DeleteLayer(void) { LY_DeleteLayer (m68k_areg (regs, 1)); return 0; }
  1481.  
  1482. static void LY_LockLayer1(uaecptr layer)
  1483. {
  1484.     uaecptr li = get_long (layer + 68);
  1485.     struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq (&MyLayerInfo_list, get_long (li + 84));
  1486.     struct MyLayer *l = (struct MyLayer *)find_uniq (&mli->layer_list, get_long (layer + 24));
  1487.  
  1488.     LY_LockLayer(layer);
  1489.     build_cliprects (l);
  1490. }
  1491. static uae_u32 LY_TryLockLayer1(uaecptr layer)
  1492. {
  1493.     uaecptr li = get_long (layer + 68);
  1494.     struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq (&MyLayerInfo_list, get_long (li + 84));
  1495.     struct MyLayer *l = (struct MyLayer *)find_uniq (&mli->layer_list, get_long (layer + 24));
  1496.  
  1497.     if (!LY_TryLockLayer(layer))
  1498.     return 0;
  1499.     build_cliprects (l);
  1500.     return 1;
  1501. }
  1502. static uae_u32 gfx_TryLockLayer(void) { return LY_TryLockLayer1 (m68k_areg(regs, 5));  }
  1503. static uae_u32 gfx_LockLayer(void) { LY_LockLayer1 (m68k_areg(regs, 5)); return 0; }
  1504. static uae_u32 gfx_UnlockLayer(void) { LY_UnlockLayer(m68k_areg(regs, 5)); return 0; }
  1505. static uae_u32 layers_LockLayer(void) { LY_LockLayer1 (m68k_areg(regs, 1)); return 0; }
  1506. static uae_u32 layers_LockLayers(void) { LY_LockLayers(m68k_areg(regs, 0)); return 0; }
  1507. static uae_u32 layers_LockLayerInfo(void) { LY_LockLayerInfo(m68k_areg(regs, 0)); return 0; }
  1508. static uae_u32 layers_UnlockLayer(void) { LY_UnlockLayer(m68k_areg(regs, 0)); return 0; }
  1509. static uae_u32 layers_UnlockLayers(void) { LY_UnlockLayers(m68k_areg(regs, 0)); return 0; }
  1510. static uae_u32 layers_UnlockLayerInfo(void) { LY_UnlockLayerInfo(m68k_areg(regs, 0)); return 0; }
  1511.  
  1512. static uae_u32 layers_ScrollLayer(void)
  1513. {
  1514.     abort();
  1515. }
  1516.  
  1517. static uae_u32 layers_SizeLayer(void)
  1518. {
  1519.     abort();
  1520. }
  1521.  
  1522. static uae_u32 layers_MoveLayer(void)
  1523. {
  1524.     abort();
  1525. }
  1526.  
  1527. static uae_u32 layers_UpfrontLayer(void)
  1528. {
  1529.     abort();
  1530. }
  1531.  
  1532. static uae_u32 layers_BehindLayer(void)
  1533. {
  1534.     abort();
  1535. }
  1536.  
  1537. static uae_u32 layers_MoveLayerInFrontOf(void)
  1538. {
  1539.     abort();
  1540. }
  1541.  
  1542. static uae_u32 layers_BeginUpdate(void)
  1543. {
  1544.     return 1;
  1545. }
  1546.  
  1547. static uae_u32 layers_EndUpdate(void)
  1548. {
  1549.     return 0;
  1550. }
  1551.  
  1552. static uae_u32 layers_WhichLayer(void)
  1553. {
  1554.     abort();
  1555. }
  1556.  
  1557. static uae_u32 layers_InstallClipRegion(void)
  1558. {
  1559.     return 0;
  1560. }
  1561.  
  1562. static uae_u32 layers_SwapBitsRastPortClipRect(void)
  1563. {
  1564.     abort();
  1565. }
  1566.  
  1567. /*
  1568.  *  Initialization
  1569.  */
  1570. static uae_u32 gfxlib_init(void)
  1571. {
  1572.     uae_u32 old_arr;
  1573.     uaecptr sysbase=m68k_areg(regs, 6);
  1574.     int i=0;
  1575.  
  1576.     /* Install new routines */
  1577.     m68k_dreg(regs, 0)=0;
  1578.     m68k_areg(regs, 1)=gfxlibname;
  1579.     gfxbase=CallLib(sysbase, -408);  /* OpenLibrary */
  1580.     m68k_dreg(regs, 0)=0;
  1581.     m68k_areg(regs, 1)=layerslibname;
  1582.     layersbase=CallLib(sysbase, -408);  /* OpenLibrary */
  1583.  
  1584.     libemu_InstallFunctionFlags(gfxl_WritePixel, gfxbase, -324, TRAPFLAG_EXTRA_STACK, "");
  1585.     libemu_InstallFunctionFlags(gfxl_BltClear, gfxbase, -300, 0, "");
  1586.     libemu_InstallFunctionFlags(gfxl_AndRegionRegion, gfxbase, -624, TRAPFLAG_EXTRA_STACK, "");
  1587.     libemu_InstallFunctionFlags(gfxl_OrRegionRegion, gfxbase, -612, TRAPFLAG_EXTRA_STACK, "");
  1588.     libemu_InstallFunctionFlags(gfxl_XorRegionRegion, gfxbase, -618, TRAPFLAG_EXTRA_STACK, "");
  1589.     libemu_InstallFunctionFlags(gfxl_AndRectRegion, gfxbase, -504, TRAPFLAG_EXTRA_STACK, "");
  1590.     libemu_InstallFunctionFlags(gfxl_OrRectRegion, gfxbase, -510, TRAPFLAG_EXTRA_STACK, "");
  1591.     libemu_InstallFunctionFlags(gfxl_XorRectRegion, gfxbase, -558, TRAPFLAG_EXTRA_STACK, "");
  1592.     libemu_InstallFunctionFlags(gfxl_ClearRectRegion, gfxbase, -522, TRAPFLAG_EXTRA_STACK, "");
  1593.  
  1594. #if 0
  1595. #define MAYBE_FUNCTION(a) NULL
  1596. #else
  1597. #define MAYBE_FUNCTION(a) (a)
  1598. #endif
  1599. #if 0
  1600.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_TryLockLayer), gfxbase, -654, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "AttemptLockLayerRom");
  1601.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_LockLayer), gfxbase, -432, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "LockLayerRom");
  1602.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_UnlockLayer), gfxbase, -438, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "UnlockLayerRom");
  1603.  
  1604.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_InitLayers), layersbase, -30, TRAPFLAG_EXTRA_STACK, "InitLayers");
  1605.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_CreateUpfrontLayer), layersbase, -36, TRAPFLAG_EXTRA_STACK, "CreateUpfrontLayer");
  1606.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_CreateBehindLayer), layersbase, -42, TRAPFLAG_EXTRA_STACK, "CreateBehindLayer");
  1607.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UpfrontLayer), layersbase, -48, TRAPFLAG_EXTRA_STACK, "UpfrontLayer");
  1608.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_BehindLayer), layersbase, -54, TRAPFLAG_EXTRA_STACK, "BehindLayer");
  1609.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_MoveLayer), layersbase, -60, TRAPFLAG_EXTRA_STACK, "MoveLayer");
  1610.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_SizeLayer), layersbase, -66, TRAPFLAG_EXTRA_STACK, "SizeLayer");
  1611.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_ScrollLayer), layersbase, -72, TRAPFLAG_EXTRA_STACK, "ScrollLayer");
  1612.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_BeginUpdate), layersbase, -78, TRAPFLAG_EXTRA_STACK, "BeginUpdate");
  1613.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_EndUpdate), layersbase, -84, TRAPFLAG_EXTRA_STACK, "EndUpdate");
  1614.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_DeleteLayer), layersbase, -90, TRAPFLAG_EXTRA_STACK, "DeleteLayer");
  1615.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayer), layersbase, -96, TRAPFLAG_EXTRA_STACK, "LockLayer");
  1616.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayer), layersbase, -102, TRAPFLAG_EXTRA_STACK, "UnlockLayer");
  1617.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayers), layersbase, -108, TRAPFLAG_EXTRA_STACK, "LockLayers");
  1618.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayers), layersbase, -114, TRAPFLAG_EXTRA_STACK, "UnlockLayers");
  1619.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayerInfo), layersbase, -120, TRAPFLAG_EXTRA_STACK, "LockLayerInfo");
  1620.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_SwapBitsRastPortClipRect), layersbase, -126, TRAPFLAG_EXTRA_STACK, "SwapBitsRastPortClipRect");
  1621.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_WhichLayer), layersbase, -132, TRAPFLAG_EXTRA_STACK, "WhichLayer");
  1622.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayerInfo), layersbase, -138, TRAPFLAG_EXTRA_STACK, "UnlockLayerInfo");
  1623.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_NewLayerInfo), layersbase, -144, TRAPFLAG_EXTRA_STACK, "NewLayerInfo");
  1624.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_DisposeLayerInfo), layersbase, -150, TRAPFLAG_EXTRA_STACK, "DisposeLayerInfo");
  1625.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_FattenLayerInfo), layersbase, -156, TRAPFLAG_EXTRA_STACK, "FattenLayerInfo");
  1626.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_ThinLayerInfo), layersbase, -162, TRAPFLAG_EXTRA_STACK, "ThinLayerInfo");
  1627.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_MoveLayerInFrontOf), layersbase, -168, TRAPFLAG_EXTRA_STACK, "MoveLayerInFrontOf");
  1628.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_InstallClipRegion), layersbase, -174, TRAPFLAG_EXTRA_STACK, "InstallClipRegion");
  1629. #if 0
  1630.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -180, TRAPFLAG_EXTRA_STACK, "MoveSizeLayer");
  1631.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -186, TRAPFLAG_EXTRA_STACK, "CreateUpfrontHookLayer");
  1632.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -192, TRAPFLAG_EXTRA_STACK, "CreateBehindHookLayer");
  1633.     libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -198, TRAPFLAG_EXTRA_STACK, "InstallLayerHook");
  1634. #endif
  1635. #endif
  1636.     return 0;
  1637. }
  1638.  
  1639. /*
  1640.  *  Install the gfx-library-replacement
  1641.  */
  1642. void gfxlib_install(void)
  1643. {
  1644.     uae_u32 begin, end, resname, resid;
  1645.     int i;
  1646.  
  1647.     if(!use_gfxlib) return;
  1648.  
  1649.     fprintf(stderr, "Warning: you enabled the graphics.library replacement with -g\n"
  1650.         "This may be buggy right now, and will not speed things up much.\n");
  1651.  
  1652.     resname = ds("UAEgfxlib.resource");
  1653.     resid = ds("UAE gfxlib 0.1");
  1654.  
  1655.     gfxlibname = ds("graphics.library");
  1656.     layerslibname = ds("layers.library");
  1657.  
  1658.     begin = here();
  1659.     dw(0x4AFC);             /* RTC_MATCHuae_s16 */
  1660.     dl(begin);              /* our start address */
  1661.     dl(0);                  /* Continue scan here */
  1662.     dw(0x0101);             /* RTF_COLDSTART; Version 1 */
  1663.     dw(0x0805);             /* NT_RESOURCE; pri 5 */
  1664.     dl(resname);            /* name */
  1665.     dl(resid);              /* ID */
  1666.     dl(here() + 4);         /* Init area: directly after this */
  1667.  
  1668.     calltrap(deftrap2(gfxlib_init, TRAPFLAG_EXTRA_STACK, "")); dw(RTS);
  1669.  
  1670.     end = here();
  1671.     org(begin + 6);
  1672.     dl(end);
  1673.  
  1674.     org(end);
  1675. }
  1676. #else
  1677.  
  1678. void gfxlib_install (void)
  1679. {
  1680. }
  1681.  
  1682. #endif
  1683.